/* All functions return ints so that the user can choose to quit at any time.
   If the function returns 1, then the user requested to quit.
   If the function returns 0, then it completed successfully. */

   /*#include all the different files from group members when available*/
#include<iostream>
#include<string>
#include<vector>
#include<fstream>
#include "myDatabase.cpp"

using namespace std;
Database myDatabase;

//delete beginning whitespace in strings
string deleteFrontWhitespace(string wsline){
	string line = wsline;
	while(line.at(0)==' ')
		line.erase(0,1);
	return line;
}
//delete ending whitespace in strings
string deleteEndWhitespace(string wsline){
	string line = wsline;
	int endValue = line.length()-1;
	while(line.at(endValue)==' '){
		line.erase(endValue,1);
		endValue = line.length()-1;
	}
	return line;
}
//write a file of the entire database of relations
int writeFile(){
	//user input and filename variables
	string specifyName;
	string filename;
	//holder variables
	string relationName;
	int numberOfAttributes;
	int numberOfTuples;
	//filename1 is schema file, filename2 is data file
	string filename1;
	string filename2;
	
	//ask user for file name
	cout<<"\nWould you like to enter a name for this file? (y or n): ";
	getline(cin, specifyName);
	if(specifyName=="exit") return 1;
	if(specifyName=="y"){
		cout<<"Please enter a name for the file: ";
		getline(cin, filename);
		if(filename=="exit") return 1;
	}
	else {/*put something here, dunno what to call it*/}
	filename = deleteFrontWhitespace(filename);
	filename = deleteEndWhitespace(filename);
	filename1 = filename + "01.txt";
	filename2 = filename + "02.txt";
	//create files
	ofstream myfile1(filename1.c_str());
	ofstream myfile2(filename2.c_str());
	/*//write to the files
	for(int i=0; i<Database::myDatabase.size(); i++){
		relationName = Database::myDatabase.at(i).getName();
		numberOfAttributes = Relation::relationName.attributes.size();
		numberOfTuples = Relation::relationName.getNumRows();
		//print the relation name out to both files, followed by either the num of attributes or tuples
		myfile1<<relationName <<", " <<numberOfAttributes <<'\n';
		myfile2<<relationName <<", " <<numberOfTuples <<'\n';
		//enter rest of data into myfile1, since num of tuples doesn't matter
		for(int z=0, z<numberOfAttributes; z++){
			if(!Relation::relationName.primaryKeyList.at(z).empty()){
				myfile1<<Relation::relationName.types.at(z) <<" *" <<Relation::relationName.attributes.at(z) <<'\n';
			}
			else
				myfile1<<Relation::relationName.types.at(z) <<" " <<Relation::relationName.attributes.at(z) <<'\n';
		}
		//enter rest of data into myfile2
		for(int j=0; j<numberOfTuples; j++){
			for(int k=0; k<numberOfAttributes; k++){
				if(k==numberOfAttributes-1){
					myfile2<<Relation::relationName.at(j).at(k) <<'\n';
				}
				else
					myfile2<<Relation::relationName.at(j).at(k) <<", ";
			}
		}
		relationName.clear();
		numberOfAttributes = 0;
		numberOfTuples = 0;
	}
	*/
	myfile1.close();
	myfile2.close();
	return 0;	
}
//insert relation into database, choice of file or manual
int insertNewRelation(){
	//relation data to send to database
	string relationName;
	vector<string> attributeData;
	vector<string> attributeTypes;
	vector<string> primaryKeyData;
	//input and loop variables
	string userInput;
	string isPrimaryKey;
	string more = "y";
	//file reading variables
	string filename;
	string numOfAttributes;
	int numOfAttr;
	string type;
	string typeName;
	//check variable for completion of inputs
	string completed = "ok";//take out the instantiation when get proper calls

	//ask for choice of manual and file insert
	cout<<"\nWould you like to insert a relation manually or from a file?\n";
	cout<<"(m for manually and f for file): ";
	getline(cin, userInput);
	//check for exit request
	if(userInput=="exit") return 1;
	//check for incorrect input from file/manual choice
	if((userInput!="f")&&(userInput!="m")){
		cout<<"Incorrect form of input.\n";
		return 2;
	}
	//manual insert
	if(userInput=="m"){
		cout<<"Please enter the name of the relation: ";
		getline(cin,relationName);
		if(relationName=="exit") return 1;
		//ask for types and their names
		while(more=="y"){
			//ask for type
			cout<<"Please enter a type for this relation: ";
			getline(cin, userInput);
			if(userInput=="exit") return 1;
			attributeTypes.push_back(userInput);
			//ask for label
			cout<<"Please enter the label for this type: ";
			getline(cin, userInput);
			if(userInput=="exit") return 1;
			attributeData.push_back(userInput);
			//is primary key?
			cout<<"Is this type a primary key? (y or n): ";
			getline(cin, isPrimaryKey);
			if(isPrimaryKey=="exit") return 1;
			if(isPrimaryKey=="y")
				primaryKeyData.push_back(userInput);
			//more types?
			cout<<"Are there any more types? (y or n): ";
			getline(cin, more);
			if(more=="exit") return 1;
		}
		completed = myDatabase.createRelation(relationName, attributeData, attributeTypes, primaryKeyData);
	}

	//insert from file
	if(userInput == "f"){
		cout<<"\nPlease make sure your file is in the same directory as the executable for this project.\n";
		cout<<"Or make sure when you enter the filename and path that you use two backslashes instead of a single one.\n";
		cout<<"Please enter the name of the file, including extension: ";
		getline(cin, filename);
		if(filename=="exit") return 1;
		//put file reading here
		ifstream myfile(filename.c_str());
		if(!myfile){
			cout<<"Invalid file name.";
			return 2;
		}
		while(!myfile.eof()){
			getline(myfile, relationName, ',');
			getline(myfile, numOfAttributes);
			//convert string to int
			numOfAttributes = deleteFrontWhitespace(numOfAttributes);
			numOfAttributes = deleteEndWhitespace(numOfAttributes);
			numOfAttr = atoi(numOfAttributes.c_str());
			cout<<"\nnum of attributes: "<<numOfAttr;
			//loop to pull correct number of attributes (aka lines) from the file
			for(int i=0; i<numOfAttr; i++){
				//get type from file
				getline(myfile, type, ' ');
				cout<<"\ntype: "<<type;
				type = deleteFrontWhitespace(type);
				type = deleteEndWhitespace(type);
				//put type in vector
				attributeTypes.push_back(type);
				//get type label from file
				getline(myfile, typeName);
				cout<<"\ntype name: "<<typeName;
				typeName = deleteFrontWhitespace(typeName);
				typeName = deleteEndWhitespace(typeName);
				//check for primary key
				char s = typeName.at(0);
				if(s=='*'){
					typeName = typeName.erase(0,1);
					primaryKeyData.push_back(typeName);
				}
				else{
					primaryKeyData.push_back("");
				}
				//put type label in vector
				attributeData.push_back(typeName);
			}
			for(int j=0; j<attributeData.size(); j++)
				cout<<'\n'<<attributeData.at(j);
			completed = myDatabase.createRelation(relationName, attributeData, attributeTypes, primaryKeyData);
			relationName.clear();
			attributeData.clear();
			attributeTypes.clear();
			primaryKeyData.clear();
		}
		myfile.close();
	}
	//check for complete relation creation
	if(completed=="ok"){
		cout<<'\n';
		return 0;
	}
	if(completed!="ok"){
		cout<<completed<<'\n';
		return 2;
	}
}

int deleteRelation(){
	string relationName;
	string completed = "ok";//take out the instantiation when get proper calls
	
	cout<<"\nPlease enter the name of the relation you wish to delete: ";
	getline(cin, relationName);
	if(relationName=="exit") return 1;
	/*completed = Database::deleteRelation(relationName);*/
	if(completed=="ok") return 0;
	else{
		cout<<completed;
		return 2;
	}
}

int insertNewTuple(){
	//variables to send to database
	string relationName;
	string attribute;
	vector<string> attributeList;
	vector<string> values;
	//user input and loop variables
	string userInput;
	string more = "y";
	//file reading variables
	string filename;
	string numOfTuples;
	int numTuples;
	int numAttributes;
	string value;
	//function completed variable
	string completed = "ok";//take out the instantiation when get proper calls

	cout<<"\nWould you like to insert a tuple manually or from a file?\n";
	cout<<"(m for manually and f for file): ";
	getline(cin, userInput);
	//check for exit request
	if(userInput=="exit") return 1;
	//check for incorrect input from file/manual choice
	if((userInput!="f")&&(userInput!="m")){
		cout<<"Incorrect form of input.\n";
		return 2;
	}
	//manual insert
	if(userInput=="m"){
		cout<<"Here are the current relations in the database: ";
		vector<string> relations = myDatabase.getRelationNames();
		for(int i=0; i<relations.size(); i++)
			cout<<relations.at(i) <<", ";
		cout<<"\nPlease enter the name of the relation: ";
		getline(cin, relationName);
		if(relationName=="exit") return 1;
		//ask for the attribute label and the value for that attribute
		cout<<"These are the attribute labels of this relation: ";
		vector<string> attributes = myDatabase.getAttributes(relationName);
		cout<<flush;
		for(int j=0; j<attributes.size(); j++)
			cout<<'\n'<<attributes.at(j);
		cout<<'\n';
		while(more=="y"){
			//enter attribute label
			cout<<"Please enter the attribute label: ";
			getline(cin, attribute);
			cout<<attribute;
			attribute = deleteFrontWhitespace(attribute);
			attribute = deleteEndWhitespace(attribute);
			cout<<attribute;
			if(userInput=="exit") return 1;
			if(!myDatabase.isAttribute(relationName,attribute)) return 2;
			attributeList.push_back(attribute);
			//enter value
			cout<<"Please enter the value: ";
			getline(cin, userInput);
			if(userInput=="exit") return 1;
			values.push_back(userInput);
			//ask for more values
			cout<<"Are there any more values? (y or n): ";
			getline(cin, more);
			if(more=="exit") return 1;
		}
		completed = myDatabase.insertData(relationName,attributeList,values);
		cout<<completed;
	}
	//insert from file
	if(userInput=="f"){
		cout<<"Please make sure your file is in the same directory as the executable for this project.\n";
		cout<<"Or make sure when you enter the filename and path that you use two backslashes instead of a single one.\n";
		cout<<"Please enter the name of the file, including extension: ";
		getline(cin, filename);
		if(filename=="exit") return 1;
		//put file reading here
		ifstream myfile(filename.c_str());
		if(!myfile){
			cout<<"Invalid file name.";
			return 2;
		}
		while(!myfile.eof()){
			//pull the relation name from the file
			getline(myfile, relationName, ',');
			relationName = deleteFrontWhitespace(relationName);
			relationName = deleteEndWhitespace(relationName);
			//get the number of tuples
			getline(myfile, numOfTuples);
			numOfTuples = deleteFrontWhitespace(numOfTuples);
			numOfTuples = deleteEndWhitespace(numOfTuples);
			//convert numOfTuples to int numTuples
			numTuples = atoi(numOfTuples.c_str());
			return 0;
			//loop to pull correct number of tuples (aka lines) from the file
			for(int i=0; i<numTuples; i++){
				//loop to pull correct number of attributes from each tuple
				numAttributes = myDatabase.getAttributes(relationName).size();
				for(int j=0; j<numAttributes; j++){
					if(j==numAttributes-1){
						getline(myfile, value);
					}
					else{
						getline(myfile, value, ',');
					}
					value = deleteFrontWhitespace(value);
					value = deleteEndWhitespace(value);
					if(value.empty()){
						values.push_back("");
					}
					else{
						values.push_back(value);
					}
				}
				attributeList = myDatabase.getAttributes(relationName);
				completed = myDatabase.insertData(relationName,attributeList,values);
				if(completed!="ok"){
					cout<<completed <<'\n';
					return 2;
				}
				relationName.clear();
				attributeList.clear();
				values.clear();
			}
		}
		myfile.close();
	}
	//check for completed tuple insertion
	if(completed=="ok") return 0;
	else{
		cout<<completed;
		return 2;
	}
}

int updateTuple(){
	string relationName;
	string userInput = "y";
	string completed = "ok";//get rid of instantiation when have proper calls
	
	cout<<"\nHere are the names of the relations in this database:\n";
	//cout the relations in the database for the user
	cout<<"Please enter the relation: ";
	getline(cin, relationName);
	if(relationName=="exit") return 1;
	/*while(userInput=="y"||userInput=="yes"){
		cout<<"Here are the attributes of this tuple: ";
		if(userInput=="exit") return 1;
	}*/
	//call update tuple:  Database::updateData(relationName, attributes, changes, whereConditional)
	if(completed=="ok") return 0;
	else{
		cout<<completed <<'\n';
		return 2;
	}
}

int deleteTuple(){
	string relationName;
	string tuple;
	int tupleNum;
	string completed = "ok";//get rid of instantiation when have proper calls

	//print out the relations for the user
	cout<<"\nHere are the names of the relations currently in the database:\n";
	//cout<<Database::getRelationNames();//fix so can print out vector properly!!!!
	cout<<"Please enter the relation the tuple is in: ";
	getline(cin, relationName);
	if(relationName=="exit") return 1;
	//cout the tuples in the relation, with a number before each
	cout<<"Please enter the number of the tuple you want deleted: ";
	getline(cin,tuple);
	if(relationName=="exit") return 1;
	tupleNum = atoi(tuple.c_str());
	//call deleteTuple
	if(completed=="ok") return 0;
	else{
		cout<<completed <<'\n';
		return 2;
	}
}
/* get sum,count,min,max in query function*/
int query(){
	string completed = "ok";//get rid of instantiation when have proper calls
	string userInput, relation1, relation2;
	string more = "y";
	int numOfRelations;
	vector<string> relationNames;
	vector<string> attributeNames;
	vector<string> attributeAliases;
	string whereCondition;
	//cout all the relation names
	cout<<"\nHere are the names of the relations currently in the database:\n";
	//cout<<Database::getRelationNames();//fix so can print out vector properly!!!!
	cout<<"How many relations would you like to query? (1 or 2): ";
	getline(cin, userInput);userInput = deleteFrontWhitespace(userInput);
	userInput = deleteEndWhitespace(userInput);
	if(userInput=="exit") return 1;
	userInput = deleteFrontWhitespace(userInput);
	userInput = deleteEndWhitespace(userInput);
	numOfRelations = atoi(userInput.c_str());
	if(numOfRelations==1){
		cout<<"What relation do you want to query?: ";
		getline(cin, relation1);
		if(userInput=="exit") return 1;
		relation1 = deleteFrontWhitespace(relation1);
		relation1 = deleteEndWhitespace(relation1);
		relationNames.push_back(relation1);
		cout<<"Here are the attribute names in this relation:\n";
		//cout<<Relation::relation1.attributes;//make print properly!!
		cout<<"What attribute do you want (You can use * to select all attributes): ";
		getline(cin, userInput);
		if(userInput=="exit") return 1;
		if(userInput=="*"){
			attributeNames.push_back("*");
			attributeAliases.push_back(" ");
			whereCondition = " ";
			//completed = put call to query function, giving it relationNames, attributeNames, attributeAliases, whereConditional
			return 0;
		}
		while(more=="y"){
			userInput = relation1 + "::" + userInput;
			userInput = deleteFrontWhitespace(userInput);
			userInput = deleteEndWhitespace(userInput);
			attributeNames.push_back(userInput);
			cout<<"Do you want an alias for this attribute? (y or n):";
			getline(cin, userInput);
			if(userInput=="exit") return 1;
			if(userInput=="y"){
				cout<<"What alias do you want?: ";
				getline(cin, userInput);
				if(userInput=="exit") return 1;
				userInput = relation1 + "::" + userInput;
				userInput = deleteFrontWhitespace(userInput);
				userInput = deleteFrontWhitespace(userInput);
				attributeAliases.push_back(userInput);
			}
			cout<<"Do you want to select any more attributes? (y or n): ";
			getline(cin, more);
			if(more=="exit") return 1;
			if(more=="y"){
				cout<<"What attribute do you want?: ";
				getline(cin, userInput);
				if(userInput=="exit") return 1;
			}
		}
		cout<<"Please enter your where clause, as per SQL standards: ";
		getline(cin, whereCondition);
		if(whereCondition=="exit") return 1;
		//completed = put call to query function, giving it relationNames, attributeNames, attributeAliases, whereConditional
	}
	if(numOfRelations==2){
		cout<<"What relation do you want to query?: ";
		getline(cin, userInput);
		if(userInput=="exit") return 1;
		userInput = deleteFrontWhitespace(userInput);
		userInput = deleteEndWhitespace(userInput);
		relationNames.push_back(userInput);
		cout<<"What other relation do you want to query?: ";
		getline(cin, userInput);
		if(userInput=="exit") return 1;
		userInput = deleteFrontWhitespace(userInput);
		userInput = deleteEndWhitespace(userInput);
		relationNames.push_back(userInput);
		cout<<"Here are the attribute names in these relation:\n";
		//cout<<Relation::relation1.attributes <<'\n' <<Relation::relation2.attributes;//make print properly!!		
		cout<<"You can use * to select all attributes.";
		cout<<"For all other attributes, please remember to put attribute names in this format: relationName::attributeName\n";
		cout<<"What attribute do you want: ";
		getline(cin, userInput);
		if(userInput=="exit") return 1;
		if(userInput=="*"){
			attributeNames.push_back("*");
			attributeAliases.push_back(" ");
			whereCondition = " ";
			//completed = put call to query function, giving it relationNames, attributeNames, attributeAliases, whereConditional
			return 0;
		}
		while(more=="y"){
			userInput = relation1 + "::" + userInput;
			userInput = deleteFrontWhitespace(userInput);
			userInput = deleteEndWhitespace(userInput);
			attributeNames.push_back(userInput);
			cout<<"Do you want an alias for this attribute? (y or n):";
			getline(cin, userInput);
			if(userInput=="exit") return 1;
			if(userInput=="y"){
				cout<<"What alias do you want?: ";
				getline(cin, userInput);
				if(userInput=="exit") return 1;
				userInput = relation1 + "::" + userInput;
				userInput = deleteFrontWhitespace(userInput);
				userInput = deleteFrontWhitespace(userInput);
				attributeAliases.push_back(userInput);
			}
			cout<<"Do you want to select any more attributes? (y or n): ";
			getline(cin, more);
			if(more=="exit") return 1;
			if(more=="y"){
				cout<<"What attribute do you want?: ";
				getline(cin, userInput);
				if(userInput=="exit") return 1;
			}
		}
		cout<<"Please enter your where clause, as per SQL standards: ";
		getline(cin, whereCondition);
		if(whereCondition=="exit") return 1;
		//completed = put call to query function, giving it relationNames, attributeNames, attributeAliases, whereConditional
	}
	
	if(completed=="ok"){
		cout<<"Would you like to print this table to a file? (y or n): ";
		getline(cin, userInput);
		if(userInput=="exit") return 1;
		if(userInput=="y") return writeFile();
		return 0;
	}
	else{
		cout<<completed <<'\n';
		return 2;
	}
}

int print(){
	string relationName;
	cout<<"These are the relations currently in the database: ";
	vector<string> relationNames = myDatabase.getRelationNames();
	for(int i=0; i<relationNames.size(); i++)
		cout<<relationNames.at(i)<< " ";
	cout<<"\nPlease enter the name of the relation you want printed: ";
	getline(cin, relationName);
	if(relationName=="exit") return 1;
	myDatabase.printRelation(relationName);
}